package com.elitel.frame.base.service.impl;

import com.elitel.common.utils.DateUtil;
import com.elitel.common.utils.RedisUtils;
import com.elitel.frame.base.component.SysReqLogKeys;
import com.elitel.frame.base.service.CfgDbService;
import com.elitel.frame.base.service.CfgTableService;
import com.elitel.frame.base.service.SysPrjServiceService;
import com.elitel.frame.base.service.SysReqLogService;
import com.elitel.frame.main.dao.AcAppMapper;
import com.elitel.frame.main.dao.SysJobLogMapper;
import com.elitel.frame.main.dao.SysReqLogMapper;
import com.elitel.frame.main.dao.ext.ExtSysPrjserviceMapper;
import com.elitel.frame.main.entity.AcApp;
import com.elitel.frame.main.entity.SysReqLog;
import com.elitel.frame.main.entity.enums.StatEnum;
import com.elitel.frame.main.entity.vo.JobExecuteConditionVo;
import com.elitel.frame.main.entity.vo.ServerStatVO;
import com.elitel.frame.main.entity.vo.StatAnalServicesVO;
import com.elitel.frame.main.entity.vo.StatAnalTableVO;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 访问控制-调用次数统计(SysReqLog)表服务实现类
 *
 * @author makejava
 * @since 2023-12-20 18:08:59
 */
@Service("sysReqLogService")
@Slf4j
public class SysReqLogServiceImpl implements SysReqLogService {
    @Value("${isUseTenant}")
    private Boolean isUseTenant;
    @Resource
    private SysPrjServiceService prjServiceService;
    @Resource
    private AcAppMapper acAppMapper;
    @Resource
    private SysReqLogMapper sysReqLogMapper;
    @Resource
    private ExtSysPrjserviceMapper extSysPrjserviceMapper;
    @Resource
    private SysReqLogService sysReqLogService;
    @Resource
    private SysReqLogKeys sysReqLogKeys;
    @Resource
    private CfgDbService cfgDbService;
    @Resource
    private CfgTableService cfgTableService;
    @Resource
    private SysJobLogMapper sysJobLog;


    public final static String FREQUENCY = "F";

    /**
     * 分隔符
     */
    public final static String SEP = "&-&";
    /**
     * redis APP后缀key
     */
    private final static String APP = ":APP";
    /**
     * redis SERVICE后缀key
     */
    private final static String SERVICE = ":SERVICE";
    /**
     * redis DATE后缀key
     */
    private final static String DATE = ":DATE";
    /**
     * 时间格式化
     */
    private final static String YMD = "yyyyMMdd";


    @Override
    public List<List<String>> selectTopByDays(int days, String type) {
        LocalDate stdt = LocalDate.now().minusDays(days);
        List<Map<String, Object>> list = new ArrayList<>();
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
        }
        if ("APP".equals(type)) {
            list = sysReqLogMapper.selectTopAppByDate(stdt,flag,servCodes);
        }
        if ("SERVICE".equals(type)) {
            list = sysReqLogMapper.selectTopServerByDate(stdt,flag,servCodes);
        }
        // 按照get("req_count")倒序排序
        list.sort(Comparator.comparing(o -> Integer.valueOf(o.get("req_count") + "")));

        AtomicReference<BigDecimal> maxNum = new AtomicReference<>();
        list.stream().max(Comparator.comparing(o -> Integer.valueOf(o.get("req_count") + ""))).ifPresent(o -> {
            maxNum.set(new BigDecimal(o.get("req_count") + ""));
        });
        List<List<String>> resList = new ArrayList<>();
        // 结果集
        resList.add(Arrays.asList("score", "num", "name"));
        for (Map<String, Object> dbres : list) {
            List<String> res = new ArrayList<>(3);
            BigDecimal reqCount = new BigDecimal(dbres.get("req_count") + "");
            // 和最大值相比的占比
            res.add(reqCount.divide(maxNum.get(), 2, RoundingMode.UP).multiply(new BigDecimal("100")).toString());
            // 数量
            res.add(reqCount + "");
            // 名称
            res.add(dbres.get("apporservername") + "");
            resList.add(res);
        }
        return resList;
    }


    @Override
    public Map<String, Object> recentDateList(Integer days) {
        LocalDate now = LocalDate.now();
        LocalDate stdt = now.minusDays(days);
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
        }
        List<Map<String, Object>> maps = sysReqLogMapper.selectRec7Days(stdt,flag,servCodes);
        Map<String, String> dateNumMap = maps.stream().collect(Collectors.toMap(map -> {
            Object reqDate = map.get("req_date");
            if (reqDate instanceof Timestamp) {
                Timestamp timestamp = (Timestamp) reqDate;
                LocalDate date = timestamp.toLocalDateTime().toLocalDate();
                return date.format(DateTimeFormatter.ofPattern(YMD));
            } else {
                return reqDate + "";
            }
        }, map -> map.get("req_count") + ""));

        // 获取时间列表
        List<String> dateList = new ArrayList<>();
        ArrayList<String> numList = new ArrayList<>();
        for (int i = 1; i <= days; i++) {
            String date = stdt.plusDays(i).format(DateTimeFormatter.ofPattern(YMD));
            dateList.add(date);
            numList.add(dateNumMap.get(date) == null ? "0" : dateNumMap.get(date));
        }

        HashMap<String, Object> res = new HashMap<>();
        res.put("dateList", dateList);
        res.put("numList", numList);
        return res;
    }

    @Override
    public ServerStatVO serverStat(Map<String, String> params) {
        ServerStatVO serverStatVO = new ServerStatVO();
        List<Map<String, Object>> maps = prjServiceService.selectCountGroupByType();
        // 服务类型
        if (CollectionUtils.isNotEmpty(maps)) serverStatVO.setTypeNum(maps.size());
        // 服务总数
        maps.stream().map(i -> i.get("value") != null ? new BigDecimal(i.get("value") + "") : BigDecimal.ZERO).reduce(BigDecimal::add).ifPresent(i -> serverStatVO.setServerNum(i.intValue()));
        // 服务使用单位
        List<AcApp> acApps = acAppMapper.selectByPrimaryKeys(null);
        if (CollectionUtils.isNotEmpty(acApps)) serverStatVO.setAppNum(acApps.size());
        // 周服务调用次数
        Set<ZSetOperations.TypedTuple<String>> typedTuples = RedisUtils.zRangeWithScores(StatEnum.DAY7.getRedisKey(sysReqLogKeys.getCurrpre()) + DATE, 0, -1);
        typedTuples.stream().map(i -> i.getScore() == null ? BigDecimal.ZERO : BigDecimal.valueOf(i.getScore())).reduce(BigDecimal::add).ifPresent(i -> serverStatVO.setInvokeTimes(i.intValue()));
        // 累计天数
        Date date = extSysPrjserviceMapper.selectMinDate();
        Long daysBetween = DateUtil.getDaysBetween(date == null ? new Date() : date, new Date());
        serverStatVO.setDays(daysBetween.intValue());
        return serverStatVO;
    }



    @Override
    public List<Map<String, Object>> invokeRecordList(int startIdx, int endIdx, String status) {
        PageHelper.startPage(startIdx, endIdx);
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
        }
        List<Map<String, Object>> resList = sysReqLogMapper.selectDetail(status,flag,servCodes);
        return resList;
    }


    @Override
    public List<SysReqLog> getAppReqAll(String guid, String appCode, String servicename) {
        return sysReqLogMapper.getAppReqAll(guid, appCode, servicename);
    }

    @Override
    public List<SysReqLog> getAppReqCounts(String servicecode, Timestamp stm, Timestamp etm, String appCode, String servicename) {
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
        }
        return sysReqLogMapper.getAppReqCounts(servicecode, stm, etm, appCode, servicename,flag,servCodes);
    }


    @Override
    public List<SysReqLog> getAppReqCountsTm(String servicecode, String appCode, Timestamp stm, Timestamp etm) {
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
        }
        return sysReqLogMapper.getAppReqCountsTm(servicecode, appCode, stm, etm,flag,servCodes);
    }

    @Override
    public StatAnalTableVO statisticalAnalysisTables() {
        //查询数据源总数
        int dbCount = cfgDbService.getCount();
        //查询数据表总数
        int tableCount = cfgTableService.getCount();
        //查询记录数
        long recordCount = cfgTableService.getRecordCount();

        return new StatAnalTableVO(dbCount, tableCount, recordCount);
    }

    @Override
    public StatAnalServicesVO statisticalAnalysisServices() {
        //服务总数
        int serviceCount = prjServiceService.getCount();
        //数据产品总数 调用第三方api

        //服务累计使用 数据粒度是，“调用方”和“服务标识” 的“天”统计

        StatAnalServicesVO vo = new StatAnalServicesVO();
        vo.setServiceNum(serviceCount);
        String allNum = RedisUtils.get(sysReqLogKeys.getAllNum());
        vo.setDataRecordNum(Long.valueOf(StringUtils.isEmpty(allNum) ? "0" : allNum));
        return vo;
    }

    @Override
    public List<JobExecuteConditionVo> jobExecuteCondition() {
        return sysJobLog.jobExecuteCondition();
    }

}

